home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
iwf12.zip
/
KERNEL
/
IMAGEIO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-19
|
24KB
|
768 lines
/*
-------------------------------------------------------------------------------
IMAGEIO.C (Image Input Output)
CREATOR: Craig Muller P.Eng. 1991,1992,1993
cmuller@ccu.umanitoba.ca
Computer Vision Laboratory
University of Manitoba
Winnipeg, Manitoba. R3T 2N2
CANADA.
DESCRIPTION:
These procedures provide a general purpose interface to the image
data and only have compatibility with the Windows environment.
PROCEDURES:
CreateImage() - Creates an image which can be used for storing pixel data.
DestroyImage() - Frees an image used for storing pixel data.
ClearImage() - Clears an image to zero.
CopyImageData() - Copies the pixel data from source to destination image.
CopyImageRect() - Copies a rectangle of pixels from source to destination image.
CopyImageRow() - Copies a row of pixels from source to destination image.
CopyImagePal() - Copies an image palette to a destination image
DuplicateImage() - Creates a new image which is a duplicate of the original less data
ReduceImage() - Creates a new image which is a reduction of the original.
ScaleImage() - Creates a new image which scales the original into it.
MirrorImage() - Creates a new image which is a mirror of the original
FlipImage() - Creates a new image which is a flip of the original
RotateImage() - Creates a new image which is a rotation of the original
GetImagePixel() - Gets a pixel from an image at x,y and stores it in dn.
SetImagePixel() - Sets a pixel value in the source frame buffer at x,y to a value of dn.
GetImageScan() - Gets a raster line from an image at line y and stores it at dn.
GetImageRow() - Gets a row of pixels from an image and stores it at dn.
PutImageRow() - Puts a row of pixels from a buffer into an image
SetImageRow() - Sets a row of pixels to a value
GetImageCol() - Gets a column of pixels from an image and stores it at dn.
PutImageCol() - Puts a column of pixels from a buffer into an image
SetImageCol() - Sets a column of pixels to a value
GetImageRect() - Cuts a rectangle from an image and stores it in the buffer.
PutImageRect() - Pastes a rectangle from the buffer to an image.
SetImageRect() - Sets a rectangular region of pixels to a value
ImageMessage() - Puts an error message on the screen
-------------------------------------------------------------------------------
*/
#include <windows.h>
#pragma hdrstop
#include <stdio.h>
#include <dos.h>
#include <math.h>
#include <mem.h>
#include <alloc.h>
#include <string.h>
#include "kernel.h"
void CopyImageRow(IMAGE *s_image,IMAGE *d_image,int x,int y,int cb);
void CopyImageRect(IMAGE *s_image,IMAGE *d_image,RECT *rs);
/*
---------------------------------------------------------------------
ImageMessage() - Puts an error message on the screen
~~~~~~~~~~
COMMENTS:
---------------------------------------------------------------------
*/
void ImageMessage(char *sz)
{
MessageBeep(MB_ICONEXCLAMATION);
MessageBox(NULL,sz,"KERNEL ERROR (FBIO)",MB_OK | MB_ICONEXCLAMATION);
}
/*
---------------------------------------------------------------------
IMAGE *CreateImage(int w,int h)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This procedure allows the user to create a memory Frame Buffer (IMAGE)
in the PC memory space. There is no limit on the number of images
that can be created as long as there is memory space available.
Parameters:
w - width of image
h - height of image
Return value:
(IMAGE *) - pointer to the new image structure.
---------------------------------------------------------------------
*/
IMAGE *CreateImage(int w,int h)
{
char sz[80];
int i;
IMAGE *image;
// Allocate local memory space for the data structure for the IMAGE object.
image = (IMAGE *)LocalAlloc(LPTR,sizeof(IMAGE));
if (!image)
{
ImageMessage("Unable to Allocate Local Memory");
return(image);
}
if (w>MAXW)
{
sprintf(sz,"Width exceeds %d pixels, image will be truncated",MAXW);
ImageMessage(sz);
w = MAXW;
}
if (h>MAXH)
{
sprintf(sz,"Height exceeds %d pixels, image will be truncated",MAXW);
ImageMessage(sz);
h = MAXH;
}
strcpy(image->comment,"No Comments"); // Default comment string
strcpy(image->fspec,"Untitled"); // Default file name string
image->color = FALSE; // Image by default is gray
image->hres = w; // Set the image width
image->vres = h; // Set the image height
image->depth = 8; // Only uses 8 bit images
image->palsize= 256; // Default palette entries used
image->gamma = 0.5; // Default gamma value
// *** IMPORTANT ***
// Even though the width of an image can be any value, when the image
// is displayed in Windows the bitmap scan must fit on a 32 bit boundary
// or else the display will appear all garbled. Scansize is used for this.
image->scansize = (w%4) ? (w/4+1)*4 : w; // Must fit 32 bit boundary.
SetRect(&image->rc,0,0,image->hres-1,image->vres-1); // Set default client rectangle
// Since the default image is gray set the input and output LUTS
// to a gray scale.
for (i=0; i<256; ++i)
{
image->ILUT[i] = i;
}
for (i=0; i<256; ++i)
{
image-> Pal[i].peRed = i;
image-> Pal[i].peGreen = i;
image-> Pal[i].peBlue = i;
image-> Pal[i].peFlags = 0;
image-> LUT[i].peRed = i;
image-> LUT[i].peGreen = i;
image-> LUT[i].peBlue = i;
image-> LUT[i].peFlags = 0;
}
// Allocate global memory for holding the image data.
image->hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,(DWORD)image->scansize*image->vres);
if (!image->hData)
{
ImageMessage("Unable to Allocate Global Memory");
image = (IMAGE *)LocalFree((LOCALHANDLE)image);
}
return(image); // Return a pointer to the new image
}
/*
---------------------------------------------------------------------
IMAGE *DestroyImage(IMAGE *image)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Destroys a Frame Buffer object by first freeing any data memory and
then freeing the object structure. The object is returned if it cannot
be destroyed for any reason, otherwise NULL is returned if OK.
Parameters:
image - pointer to image to be destroyed
Return value:
(IMAGE *) - null pointer to image if successful.
---------------------------------------------------------------------
*/
IMAGE *DestroyImage(IMAGE *image)
{
if (image) // If the image is valid
{
if (image->hData) // If the data is valid
image->hData = GlobalFree(image->hData); // Free the image data
if (image->hData) // If the data is still valid
{ // It was unable to free it
ImageMessage("Unable to Free Global Memory");
return(image);
}
image = (IMAGE *)LocalFree((LOCALHANDLE)image); // Free the local structure
if (image) // If it is still there
{ // It was unable to free it
ImageMessage("Unable to Free Local Memory");
return(image);
}
}
return(image); // Return image pointer
}
/*
-------------------------------------------------------------------------------
IMAGE *DuplicateImage(IMAGE *image)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This procedure allows the user to duplicate a image structure
in the PC memory space. There is no limit on the number of memory FBs
that can be created as long as there is memory space available. The orginal
image is not destroyed.
Parameters:
image - pointer to source image
Return value:
(IMAGE *) - null pointer to the new image if successful.
-------------------------------------------------------------------------------
*/
IMAGE *DuplicateImage(IMAGE *image)
{
IMAGE *new_image;
// Allocate local memory space for the data structure for the IMAGE object.
new_image = (IMAGE *)LocalAlloc(LPTR,sizeof(IMAGE));
if (!new_image)
{
ImageMessage("Unable to Allocate Local Memory");
return(new_image);
}
// Copy structure information
memcpy(new_image,image,sizeof(IMAGE));
// Allocate global memory for holding the new_image data.
new_image->hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,(DWORD)new_image->scansize*new_image->vres);
if (!new_image->hData)
{
ImageMessage("Unable to Allocate Global Memory");
new_image = (IMAGE *)LocalFree((LOCALHANDLE)new_image);
return(new_image);
}
return(new_image);
}
/*
-------------------------------------------------------------------------------
void CopyImageData(IMAGE *s_image,IMAGE *d_image)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Copies the source frame buffer data to the destination frame buffer
Parameters:
s_image - pointer to source image
d_image - pointer to destination image
-------------------------------------------------------------------------------
*/
void CopyImageData(IMAGE *s_image,IMAGE *d_image)
{
RECT rs;
SetRect(&rs,0,0,d_image->hres,d_image->vres);
CopyImageRect(s_image,d_image,&rs);
}
/*
--------------------------------------------------------------------------
void CopyImageRect(IMAGE *image,RECT *r,BYTE *buf)
DESCRIPTION:
This procedure copies a rectanglar region from the memory IMAGE to a
buffer. This allows the programmer to extract a region from the image
and process it without changing the original data.
--------------------------------------------------------------------------
*/
void CopyImageRect(IMAGE *s_image,IMAGE *d_image,RECT *rs)
{
int y;
RECT rd,ro;
SetRect(&rd,0,0,d_image->hres,d_image->vres);
IntersectRect(&ro,rs,&rd);
for (y=ro.top; y<ro.bottom; ++y)
CopyImageRow(s_image,d_image,ro.left,y,ro.right-ro.left);
}
/*
-------------------------------------------------------------------------------
void CopyImageRow(IMAGE *s_image,IMAGE *d_image,int x,int y,int cb)
Copies the source frame buffer data to the destination frame buffer
Parameters:
s_image - pointer to source image
d_image - pointer to destination image
-------------------------------------------------------------------------------
*/
void CopyImageRow(IMAGE *s_image,IMAGE *d_image,int x,int y,int cb)
{
int i;
BYTE huge *hpDataSrc;
BYTE huge *hpDataDst;
BYTE huge *hpRowS;
BYTE huge *hpRowD;
hpDataSrc = (BYTE huge *)GlobalLock(s_image->hData);// Lock the IMAGE memory
hpDataDst = (BYTE huge *)GlobalLock(d_image->hData);// Lock the IMAGE memory
if (x+cb > d_image->hres)
cb = d_image->hres-x;
// Compute a pointer to the start of each image memory slice.
hpRowD = MK_HPIMAGE(d_image,hpDataDst,x,y);
hpRowS = MK_HPIMAGE(s_image,hpDataSrc,x,y);
// Copy a row of pixel numbers from the source image to destination.
for (i=0; i<cb; ++i)
*(hpRowD+i) = *(hpRowS+i);
// *** DIRECT MEM COPY - FAST, BUT NEED TO CURE SEGMENT WRAPPING PROBLEM ***
// _fmemcpy(hpRowD,hpRowS,cb);
GlobalUnlock(s_image->hData); // Unlock the IMAGE memory
GlobalUnlock(d_image->hData); // Unlock the IMAGE memory
}
/*
-------------------------------------------------------------------------------
void CopyImagePal(IMAGE *s_image,IMAGE *d_image)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Copies the palette and lookup table info from source to destination.
Parameters:
s_image - pointer to source image
d_image - pointer to destination image
-------------------------------------------------------------------------------
*/
void CopyImagePal(IMAGE *s_image,IMAGE *d_image)
{
int i;
// Copy the current palette and lookup table info
for (i=0; i<256; ++i)
{
d_image->Pal[i].peRed = s_image->Pal[i].peRed;
d_image->Pal[i].peGreen = s_image->Pal[i].peGreen;
d_image->Pal[i].peBlue = s_image->Pal[i].peBlue;
d_image->Pal[i].peFlags = 0;
d_image->LUT[i].peRed = s_image->LUT[i].peRed;
d_image->LUT[i].peGreen = s_image->LUT[i].peGreen;
d_image->LUT[i].peBlue = s_image->LUT[i].peBlue;
d_image->LUT[i].peFlags = 0;
}
}
/*
-------------------------------------------------------------------------------
void ClearImage(IMAGE *image)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Clears the frame buffer data to zero.
Parameters:
image - pointer to image to be cleared
Return value:
none
-------------------------------------------------------------------------------
*/
void ClearImage(IMAGE *image)
{
int x,y;
BYTE huge *hpData;
hpData = (BYTE huge *)GlobalLock(image->hData); /* Lock the IMAGE memory */
for (y=image->rc.top; y<image->rc.bottom; ++y)
for (x=image->rc.left; x<image->rc.right; ++x)
*(hpData+(DWORD)(image->vres-1-y)*image->scansize+x)=0;
GlobalUnlock(image->hData); /* Unlock the IMAGE memory */
}
/*
--------------------------------------------------------------------------
GetImagePixel()
~~~~~~~~~~~~
This procedure gets a pixel from the memory IMAGE and stores it into a buffer.
NOTE: to index into the image memory like an array, the index
value must be a long variable type, NOT just cast to long.
--------------------------------------------------------------------------
*/
int GetImagePixel(IMAGE *image,int x,int y,BYTE *dn)
{
BYTE huge *hpData;
// Lock the image data from moving
hpData = (BYTE huge *)GlobalLock(image->hData);
// Copy the pixel data value to the buffer
*dn = *(hpData+(DWORD)(image->vres-1-y)*image->scansize+x);
// Unlock the image data
GlobalUnlock(image->hData);
return(0);
}
/*
--------------------------------------------------------------------------
int SetImagePixel(IMAGE *image,int x,int y,int dn)
DESCRIPTION:
This procedure puts a pixel from the buffer into the memory IMAGE.
--------------------------------------------------------------------------
*/
int SetImagePixel(IMAGE *image,int x,int y,BYTE dn)
{
BYTE huge *hpData;
// Lock the image data from moving
hpData = (BYTE huge *)GlobalLock(image->hData);
// Copy the buffer value to the pixel data
*(hpData+(DWORD)(image->vres-1-y)*image->scansize+x) = dn;
// Unlock the image data
GlobalUnlock(image->hData);
return(0);
}
/*
--------------------------------------------------------------------------
int GetImageScan(IMAGE *image,int y,BYTE *dn)
DESCRIPTION:
This procedure gets a row of bytes from the memory IMAGE and stores
it into a buffer. This allows the user to extract a horizontal slice
of the image.
NOTE: to index into the image memory like an array, the index
value must be a long variable type, NOT just cast to long.
--------------------------------------------------------------------------
*/
int GetImageScan(IMAGE *image,int y,BYTE *dn)
{
WORD x;
BYTE huge *hpData;
// Lock the image data from moving
hpData = (BYTE huge *)GlobalLock(image->hData);
for (x=0; x<image->hres; ++x)
*(dn+x) = *(hpData+(DWORD)(image->vres-1-y)*image->scansize+x);
// Unlock the image data
GlobalUnlock(image->hData);
return(0);
}
/*
--------------------------------------------------------------------------
int GetImageRow(IMAGE *image,int x,int y,BYTE *dn,int cb)
DESCRIPTION:
This procedure gets a row of bytes from the memory IMAGE and stores
it into a buffer. This allows the user to extract a horizontal slice
of any length from the image data. The slice can be longer or shorter
than the length of a single raster line.
NOTE: to index into the image memory like an array, the index
value must be a long variable type, NOT just cast to long.
--------------------------------------------------------------------------
*/
int GetImageRow(IMAGE *image,int x,int y,BYTE *dn,int cb)
{
int n;
BYTE huge *hpData;
// Lock the image data from moving
hpData = (BYTE huge *)GlobalLock(image->hData);
// If the count is positive, copy the pixel data normally
if (cb>0)
for (n=0; n<cb; ++n)
if (x+n < image->hres)
dn[n] = *(hpData + (DWORD)(image->vres-1-y)*image->scansize + x + n);
// If the count is negative, copy the pixel data in reverse
if (cb<0)
for (n=0; n>cb; --n)
if (x+n >= 0)
dn[-n] = *(hpData + (DWORD)(image->vres-1-y)*image->scansize + x + n);
// Unlock the image data
GlobalUnlock(image->hData);
return(0);
}
/*
--------------------------------------------------------------------------
int PutImageRow(IMAGE *image,int x,int y,BYTE *dn,int cb)
DESCRIPTION:
NOTE: to index into the image memory like an array, the index
value must be a long variable type, NOT just cast to long.
--------------------------------------------------------------------------
*/
int PutImageRow(IMAGE *image,int x,int y,BYTE *dn,int cb)
{
int n;
BYTE huge *hpData;
// Lock the image data from moving
hpData = (BYTE huge *)GlobalLock(image->hData);
// If the count is positive, copy the pixel data normally
if (cb>0)
for (n=0; n<cb; ++n)
if (x+n < image->hres)
*(hpData + (DWORD)(image->vres-1-y)*image->scansize + x + n) = dn[n];
// If the count is negative, copy the pixel data in reverse
if (cb<0)
for (n=0; n>cb; --n)
if (x+n >= 0)
*(hpData + (DWORD)(image->vres-1-y)*image->scansize + x + n) = dn[-n];
// Unlock the image data
GlobalUnlock(image->hData);
return(0);
}
/*
--------------------------------------------------------------------------
int GetImageCol(IMAGE *image,int x,int y,BYTE *dn,int cb)
DESCRIPTION:
This procedure gets a column of bytes from the memory IMAGE and stores
it into a buffer. This allows the user to extract a horizontal slice
of any length from the image data. The slice can be shorter but not
longer than the height of the IMAGE.
NOTE: to index into the image memory like an array, the index
value must be a long variable type, NOT just cast to long.
RETURN: Integer indicating success(0) or fail(-1).
--------------------------------------------------------------------------
*/
int GetImageCol(IMAGE *image,int x,int y,BYTE *dn,int cb)
{
int n;
BYTE huge *hpData;
// Lock the image data from moving
hpData = (BYTE huge *)GlobalLock(image->hData);
// If the count is positive, copy the pixel data normally
if (cb>0)
for (n=0; n<cb; ++n)
if (y+n < image->vres)
dn[n] = *(hpData + (DWORD)(image->vres-1-(y+n))*image->scansize + x);
// If the count is negative, copy the pixel data in reverse
if (cb<0)
for (n=0; n>cb; --n)
if (y+n >= 0)
dn[-n] = *(hpData + (DWORD)(image->vres-1-(y+n))*image->scansize + x);
// Unlock the image data
GlobalUnlock(image->hData);
return(0);
}
/*
--------------------------------------------------------------------------
int PutImageCol(IMAGE *image,int x,int y,BYTE *dn,int cb)
DESCRIPTION:
This procedure gets a column of bytes from the memory IMAGE and stores
it into a buffer. This allows the user to extract a horizontal slice
of any length from the image data. The slice can be shorter but not
longer than the height of the IMAGE.
NOTE: to index into the image memory like an array, the index
value must be a long variable type, NOT just cast to long.
RETURN: Integer indicating success(0) or fail(-1).
--------------------------------------------------------------------------
*/
int PutImageCol(IMAGE *image,int x,int y,BYTE *dn,int cb)
{
int n;
BYTE huge *hpData;
// Lock the image data from moving
hpData = (BYTE huge *)GlobalLock(image->hData);
// If the count is positive, copy the pixel data normally
if (cb>0)
for (n=0; n<cb; ++n)
if (y+n < image->vres)
*(hpData + (DWORD)(image->vres-1-(y+n))*image->scansize + x) = dn[n];
// If the count is negative, copy the pixel data in reverse
if (cb<0)
for (n=0; n>cb; --n)
if (y+n >= 0)
*(hpData + (DWORD)(image->vres-1-(y+n))*image->scansize + x) = dn[-n];
// Unlock the image data
GlobalUnlock(image->hData);
return(0);
}
/*
--------------------------------------------------------------------------
int GetImageRect(IMAGE *image,RECT *r,BYTE *buf)
DESCRIPTION:
This procedure copies a rectanglar region from the memory IMAGE to a
buffer. This allows the programmer to extract a region from the image
and process it without changing the original data.
--------------------------------------------------------------------------
*/
int GetImageRect(IMAGE *image,RECT *rc,BYTE *buf)
{
int x0,y0,y,w,h;
x0 = rc->left;
y0 = rc->top;
w = rc->right - rc->left;
h = rc->bottom - rc->top;
for (y=0; y<h; y++)
GetImageRow(image,x0,y0+y,buf+(y*w),w);
return(0);
}
/*
--------------------------------------------------------------------------
int PutImageRect(IMAGE *image,RECT *r,BYTE *buf)
DESCRIPTION:
This procedure copies a rectanglar region from the buffer to the memory
IMAGE. This allows the programmer to paste a processed region to the image.
--------------------------------------------------------------------------
*/
int PutImageRect(IMAGE *image,RECT *rc,BYTE *buf)
{
int x0,y0,y,w,h;
x0 = rc->left;
y0 = rc->top;
w = rc->right - rc->left;
h = rc->bottom - rc->top;
for (y=0; y<h; y++)
PutImageRow(image,x0,y0+y,buf+(y*w),w);
return(0);
}
/*
--------------------------------------------------------------------------
int SetImageRow(IMAGE *image,int x,int y,int Length,BYTE dn)
DESCRIPTION:
This procedure puts a line from a buffer into the memory IMAGE.
NOTE: A length of 0 is one pixel long. A length of 1 is two pixels
long. That is why length is incremented before being used.
--------------------------------------------------------------------------
*/
int SetImageRow(IMAGE *image,int x,int y,int Length,BYTE dn)
{
if (x+Length > image->scansize)
Length=image->scansize-x;
while (Length--)
SetImagePixel(image,x++,y,dn);
return(0);
}
/*
--------------------------------------------------------------------------
int SetImageCol(IMAGE *image,int x,int y,int Length,BYTE dn)
DESCRIPTION:
This procedure puts a line from a buffer into the memory IMAGE.
NOTE: A length of 0 is one pixel long. A length of 1 is two pixels
long. That is why length is incremented before being used.
--------------------------------------------------------------------------
*/
int SetImageCol(IMAGE *image,int x,int y,int Length,BYTE dn)
{
if (x<0 || y<0 || x>=image->scansize || y>=image->vres) /* Check bounds */
return(-1);
if (y+Length > image->vres)
Length=image->vres-y;
while (Length--)
SetImagePixel(image,x,y++,dn);
return(0);
}
/*
--------------------------------------------------------------------------
SetImageRect() - Draws a filled rectanglar region in the memory IMAGE
~~~~~~~~~~~~~~
DESCRIPTION:
Draws a filled rectanglar region in the memory IMAGE with the grey level
given in the byte buffer.
--------------------------------------------------------------------------
*/
int SetImageRect(IMAGE *image,RECT *r,BYTE dn)
{
SetImageCol(image,r->left ,r->top ,r->bottom - r->top,dn);
SetImageCol(image,r->right,r->top ,r->bottom - r->top,dn);
SetImageRow(image,r->left ,r->top ,r->bottom - r->top,dn);
SetImageRow(image,r->left ,r->bottom,r->bottom - r->top,dn);
return(0);
}